package pers.cj.pdos.controller;


import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ResponseBody;
import pers.cj.pdos.controller.base.BaseController;
import pers.cj.pdos.controller.entity.ResponseData;
import pers.cj.pdos.controller.entity.ResponseEntity;
import pers.cj.pdos.controller.entity.ResponseList;
import pers.cj.pdos.entity.*;
import pers.cj.pdos.excel.ExcelBorrowIn;
import pers.cj.pdos.excel.ExcelBorrowOut;
import pers.cj.pdos.service.*;
import pers.cj.pdos.task.CleanTempExcelTask;
import pers.cj.pdos.utils.*;
import pers.cj.pdos.vo.*;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 借出单生成后需要仓库管理关出库操作；后面如果是转销售后，状态改成已归还;如果是还的操作，则仓库管理员还需要进行入库操作 前端控制器
 * </p>
 *
 * @author chenj
 * @since 2019-11-04
 */
@Controller
@RequestMapping("/house")
public class BorrowOutController extends BaseController {
    @Autowired
    IBorrowOutService borrowOutService;
    @Autowired
    IHouseOutService houseOutService;
    @Autowired
    IHouseOutGoodsService houseOutGoodsService;
    @Autowired
    ISaleService saleService;
    @Autowired
    IBorrowOutBackService borrowOutBackService;

    @RequiresPermissions("borrowOut:query")
    @RequestMapping("/borrowOut")
    public String borrowOut(){
        return "borrowOut/borrowOut";
    }

    @RequiresPermissions("borrowOut:insert")
    @RequestMapping("/borrowOutNew")
    public String borrowOutNew(){
        return "borrowOut/borrowOutNew";
    }

    @RequiresPermissions("borrowOut:query")
    @RequestMapping("/borrowOutDetail")
    public String borrowOutDetail(Model model, String id){
        model.addAttribute("id",id);
        return "borrowOut/borrowOutDetail";
    }

    @ResponseBody
    @RequiresPermissions("borrowOut:query")
    @RequestMapping("/borrowOut/getList")
    public ResponseList getList(int page,
                                int limit,
                                String close,
                                String search,
                                String no,
                                String goodsName,
                                String remark,
                                String custom,
                                String date1,
                                String date2,
                                String storeId,
                                String userId,
                                String makeTime1,
                                String makeTime2,
                                String houseId,
                                String makeUserId,
                                String outStatus){
        Company company = getCompany();
        UserVo userVo = getLoginUserVo();

        List<BorrowOutVo> list = borrowOutService.listVo(company.getId(),
                page,
                limit,
                Utils.genBoolean(close),
                Utils.genLikeData(search),
                Utils.genLikeData(no),
                Utils.genLikeData(goodsName),
                Utils.genLikeData(remark),
                Utils.genLikeData(custom),
                Utils.genDate(makeTime1),
                Utils.genDate(makeTime2),
                storeId,
                PdosUtils.getViewOrderStoreId(userVo,null),
                PdosUtils.getViewOrderUserId(userVo,userId),
                Utils.genDate(date1),
                Utils.genDate(date2),
                houseId,
                makeUserId,
                Utils.genInteger(outStatus));
        long count = borrowOutService.count(company.getId(),
                Utils.genBoolean(close),
                Utils.genLikeData(search),
                Utils.genLikeData(no),
                Utils.genLikeData(goodsName),
                Utils.genLikeData(remark),
                Utils.genLikeData(custom),
                Utils.genDate(makeTime1),
                Utils.genDate(makeTime2),
                storeId,
                PdosUtils.getViewOrderStoreId(userVo,null),
                PdosUtils.getViewOrderUserId(userVo,userId),
                Utils.genDate(date1),
                Utils.genDate(date2),
                houseId,
                makeUserId,
                Utils.genInteger(outStatus));
        return ResponseList.success(count,list);
    }

    @ResponseBody
    @RequiresPermissions("borrowOut:insert")
    @RequestMapping("/borrowOut/add")
    public ResponseEntity add(@RequestBody BorrowOutVo borrowOutVo){

        Company company = getCompany();
        BusinessSet businessSet = getBusinessSet();

        if (Utils.isEmpty(borrowOutVo.getNo())){
            return ResponseEntity.fail("编号不能为空");
        }

        if (Utils.isEmpty(borrowOutVo.getBorrowOutGoodsVoList())){
            return ResponseEntity.fail("请选择任何商品");
        }

        if (borrowOutVo.getDate() == null){
            return ResponseEntity.fail("业务日期不能为空");
        }

        if (borrowOutVo.getBackDate() == null){
            return ResponseEntity.fail("预计归还日期不能为空");
        }

        if (borrowOutService.checkNo(borrowOutVo.getNo(),company.getId())){
            return ResponseEntity.fail("编号已被使用");
        }

        if (getHouseLocking(borrowOutVo.getHouseId())) {
            return ResponseEntity.fail("仓库被锁定，请更换仓库");
        }

        BorrowOut borrowOut = DataUtil.genEntityFromVo(BorrowOut.class,borrowOutVo);
        DataUtil.processEntity(company,borrowOut);
        borrowOut.setClose(false);
        borrowOut.setOutStatus(1);
        borrowOut.setMakeUserId(getLoginUserId());
        borrowOut.setMakeTime(borrowOut.getTime());
        if (!PdosUtils.houseInOut(businessSet)) {
            borrowOut.setStatus(1);
        } else {
            borrowOut.setStatus(2);
        }


        List<BorrowOutGoods> borrowOutGoodsList = new ArrayList<>();
        List<GoodsSn> goodsSnList = new ArrayList<>();
        List<GoodsSnLog> goodsSnLogList = new ArrayList<>();
        for (BorrowOutGoodsVo vo:borrowOutVo.getBorrowOutGoodsVoList()) {
            BorrowOutGoods entity = DataUtil.genEntityFromVo(BorrowOutGoods.class, vo);
            DataUtil.processEntity(company,entity);
            entity.setBorrowOutId(borrowOut.getId());
            entity.setHasNumber(new BigDecimal(0));
            entity.setSaleNumber(new BigDecimal(0));
            entity.setWaitNumber(vo.getNumber());
            borrowOutGoodsList.add(entity);

            if (!Utils.isEmpty(vo.getGoodsSnList())){
                for (GoodsSn goodsSn : vo.getGoodsSnList()) {
                    goodsSnList.add(goodsSn);

                    GoodsSnLog log = new GoodsSnLog();
                    DataUtil.processEntity(company,log);
                    log.setGoodsId(goodsSn.getGoodsId());
                    log.setSn(goodsSn.getSn());
                    log.setType(10);
                    log.setBorrowOutGoodsId(entity.getId());
                    goodsSnLogList.add(log);
                }
            }
        }



        borrowOutService.insert(businessSet, borrowOut,borrowOutGoodsList, goodsSnList,goodsSnLogList);

        if (!Utils.isEmpty(goodsSnList) && PdosUtils.houseInOut(businessSet)) {
            //已启用待出库入管理，但是前台传入了sn号，提示
            return ResponseEntity.success("处理成功，管理员在您新增单据过程中启用了出入库管理，录入的sn需要在入库时录入");
        }
        return ResponseEntity.success();
    }

    @ResponseBody
    @RequiresPermissions("borrowOut:close")
    @RequestMapping("/borrowOut/close")
    public ResponseEntity close(@RequestBody BorrowOut borrowOut){
        //检查是否已经关闭
        if (borrowOutService.checkClose(borrowOut)){
            return ResponseEntity.fail("该单据已被关闭，不能重复关闭");
        }


        if(saleService.count(new QueryWrapper<Sale>().eq("close",false).eq("borrow_out_id", borrowOut.getId())) > 0) {
            return ResponseEntity.fail("该借入单已产生销售单，无法作废。");
        }

        if(borrowOutBackService.count(new QueryWrapper<BorrowOutBack>().eq("close",false).eq("borrow_out_id", borrowOut.getId())) > 0) {
            return ResponseEntity.fail("该借入单已产生归还单，无法作废。");
        }

        if(houseOutService.checkByLinkId(borrowOut.getId())) {
            return ResponseEntity.fail("该订单存在出库单，请先作废对应的出库单");
        }

        try {
            borrowOutService.close(borrowOut, getBusinessSet());
            return ResponseEntity.success();
        }catch (Exception e) {
            return ResponseEntity.fail("关闭订单失败");
        }
    }

    @ResponseBody
    @RequestMapping("/borrowOut/getVoById")
    public ResponseData getVoById(String id) {
        return ResponseData.success(borrowOutService.getVoById(id));
    }

    @ResponseBody
    @RequestMapping("/borrowOut/getVoByIdWithCanTransfer")
    public ResponseData getVoByIdWithCanTransfer(String id) {
        BorrowOutVo borrowOutVo = borrowOutService.getVoById(id);
        if (borrowOutVo == null) {
            return ResponseData.fail("未找到单据");
        }


        //获取到此单的已经出库的数量
        if (borrowOutVo.getStatus() != 1) {
            //由入库单入库的，需要取得该进货的每个商品的入库数量
            List<HouseOutGoods> houseOutGoodsList = houseOutGoodsService.listByLinkId(id);
            Map<String, BigDecimal> houseOutMap = new HashMap<>();//key-goodsId value-number
            for (HouseOutGoods houseOutGoods : houseOutGoodsList) {
                String borrowOutGoodsId = houseOutGoods.getBorrowOutGoodsId();
                BigDecimal number = houseOutGoods.getNumber();
                if (houseOutMap.containsKey(borrowOutGoodsId)) {
                    //若存在，则累加数量
                    houseOutMap.put(borrowOutGoodsId, houseOutMap.get(borrowOutGoodsId).add(number));
                } else {
                    //不存在，则新建
                    houseOutMap.put(borrowOutGoodsId, number);
                }
            }

            BigDecimal zero = new BigDecimal(0);
            //新组成的数据
            List<BorrowOutGoodsVo> borrowOutGoodsVoList = new ArrayList<>();
            for (BorrowOutGoodsVo vo : borrowOutVo.getBorrowOutGoodsVoList()) {
                //已出库，且还有待转数量的商品
                if (houseOutMap.containsKey(vo.getId()) && vo.getWaitNumber().compareTo(zero)==1) {
                    //将已存在进货单对应出库单的商品添加到新内容，并将数量重新赋值
                    if (houseOutMap.get(vo.getId()).compareTo(vo.getWaitNumber()) == -1) {
                        vo.setWaitNumber(houseOutMap.get(vo.getId()));
                    }
                    vo.setNumber(vo.getWaitNumber());
                    vo.setAmount(vo.getNumber().multiply(vo.getPrice()));//重新计算器总额
                    borrowOutGoodsVoList.add(vo);
                }
            }
            borrowOutVo.setBorrowOutGoodsVoList(borrowOutGoodsVoList);
        }

        return ResponseData.success(borrowOutVo);
    }

    /**
     * 先更具请求数据
     * @throws IOException
     */
    @ResponseBody
    @RequiresPermissions("borrowOut:export")
    @RequestMapping("/borrowOut/export")
    public ResponseData export(String close,
                               String search,
                               String no,
                               String goodsName,
                               String remark,
                               String custom,
                               String date1,
                               String date2,
                               String storeId,
                               String userId,
                               String makeTime1,
                               String makeTime2,
                               String houseId,
                               String makeUserId,
                               String outStatus){
        Company company = getCompany();
        UserVo userVo = getLoginUserVo();

        List<BorrowOutVo> list = borrowOutService.listVo(company.getId(),
                null,
                null,
                Utils.genBoolean(close),
                Utils.genLikeData(search),
                Utils.genLikeData(no),
                Utils.genLikeData(goodsName),
                Utils.genLikeData(remark),
                Utils.genLikeData(custom),
                Utils.genDate(makeTime1),
                Utils.genDate(makeTime2),
                storeId,
                PdosUtils.getViewOrderStoreId(userVo,null),
                PdosUtils.getViewOrderUserId(userVo,userId),
                Utils.genDate(date1),
                Utils.genDate(date2),
                houseId,
                makeUserId,
                Utils.genInteger(outStatus));
        String fileName = "借出单列表" + DateUtils.getDate(new Date(), DateUtils.YYYYMMDDHHMMSSSS) + ".xlsx";
        try {
            String path = FileProperUtil.getInstance().getVal("excel.temp");
            OutputStream out = new FileOutputStream(path+fileName);
            ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX,true);
            Sheet sheet1 = new Sheet(1,0, ExcelBorrowOut.class);
            sheet1.setSheetName("借出单信息");
            writer.write(genExcelList(list), sheet1);
            writer.finish();
            out.close();
            CleanTempExcelTask.put(fileName,new Date().getTime());
            return ResponseData.success(fileName);
        } catch (IOException e) {
            return ResponseData.fail("订单列表导出失败");
        }
    }

    private List<ExcelBorrowOut> genExcelList(List<BorrowOutVo> borrowOutVoList) {
        List<ExcelBorrowOut> list = new ArrayList<>();
        for (BorrowOutVo vo : borrowOutVoList){
            ExcelBorrowOut excel = new ExcelBorrowOut();
            excel.setDate(DateUtils.getDate(vo.getDate(), DateUtils.YYYY_MM_DD));
            excel.setNo(vo.getNo());

            excel.setCustomNo(vo.getCustom().getNo());
            excel.setCustom(vo.getCustom().getName());
            String goods = "";
            for (BorrowOutGoodsVo borrowOutGoodsVo : vo.getBorrowOutGoodsVoList()){
                goods += borrowOutGoodsVo.getGoodsVo().getName() + "、";
            }
            excel.setGoods(goods);
            excel.setBackDate(DateUtils.getDate(vo.getBackDate(), DateUtils.YYYY_MM_DD));
            excel.setStore(vo.getHouseVo().getStore().getName());
            excel.setHouse(vo.getHouseVo().getName());
            if (vo.getOutStatus() == 1){
                excel.setOutStatus("未归还");
            } else if (vo.getOutStatus() == 2){
                excel.setOutStatus("部分归还");
            } else {
                excel.setOutStatus("全部归还");
            }

            excel.setUser(vo.getUser().getName());
            excel.setMakeUser(vo.getMakeUser().getName());
            excel.setRemark(vo.getRemark());
            excel.setClose(vo.getClose() ? "是":"否");
            list.add(excel);
        }
        return list;
    }
}
